package com.maiikun.aqs;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

public class MyLock {

    AtomicInteger status = new AtomicInteger(0);
    Thread owner = null; // 明确记录锁的持有者
    AtomicReference<ThreadNode> head = new AtomicReference<>(new ThreadNode());
    AtomicReference<ThreadNode> tail = new AtomicReference<>(head.get());


    public void lock() {
        if (status.get() == 0) {
            if (Thread.currentThread().equals(owner)) {
                // 获取到锁
                owner = Thread.currentThread();
                // 打印并自增 + 1;
                System.out.println(Thread.currentThread().getName() + "当前线程直接获取到锁" + "   "+ "重入" + status.getAndIncrement());
                return;
            }
        }else {
            if(owner.equals(Thread.currentThread())) {
                // 重入操作
                System.out.println(Thread.currentThread().getName() + "   "+ "重入次数" + status.incrementAndGet());
                return;
            }
        }


        // 获取锁失败,加入到链表中
        ThreadNode curNode = new ThreadNode(Thread.currentThread());

        while (true) {
            ThreadNode tailNode = tail.get();
            if (tail.compareAndSet(tailNode, curNode)) {
                System.out.println(Thread.currentThread().getName() + "当前线程加入到链表");
                curNode.pre = tailNode;
                tailNode.next = curNode;

                break;
            }
        }

        while (true) {
            if (curNode.pre == head.get() && status.compareAndSet(0,1)) {
                owner = Thread.currentThread();
                head.set(curNode);
                curNode.pre.next = null;
                curNode.pre = null;
                return;
            }
            LockSupport.park();
        }

    }

    public void unlock() {
        if (owner != Thread.currentThread()) {
            throw new IllegalStateException(Thread.currentThread().getName() + "当前线程未持有锁,不能唤醒");
        }

        int i = status.get();
        if (i > 1) {
            System.out.println(Thread.currentThread().getName() + "释放 : 当前线程还持有重入锁" + status.decrementAndGet() + "次");
            return;
        }

        if (i < 0) {
            throw new IllegalStateException(Thread.currentThread().getName() + "释放锁失败,不要重复释放锁");
        }

        ThreadNode headNode = head.get();
        ThreadNode next = headNode.next;
        status.set(0);

        if (next != null) {
            System.out.println(Thread.currentThread().getName() + "唤醒了" + next.thread.getName());
            LockSupport.unpark(next.thread);
        }
    }

    static class ThreadNode {
        Thread thread;
        ThreadNode pre;
        ThreadNode next;

        public ThreadNode() {
        }

        public ThreadNode(Thread thread) {
            this.thread = thread;
            this.pre = null;
            this.next = null;
        }
    }
}